#pragma once
#include <vector>

using namespace std;

namespace VoxelCore{

	struct Point3d
	{
		double x, y, z;

		Point3d(){};
		Point3d(const double &in_x, const double &in_y, const double &in_z):x(in_x),y(in_y),z(in_z){}
		Point3d operator +(const Point3d &pt){return Point3d(pt.x + x, pt.y + y, pt.z + z);}
		Point3d operator -(const Point3d &pt){return Point3d(x - pt.x, y - pt.y, z - pt.z);}
		Point3d& operator =(const Point3d &pt){x = pt.x; y = pt.y; z = pt.z; return (*this);}
		Point3d operator * (const Point3d &pt){return Point3d(pt.x * x, pt.y * y, pt.z * z);}
		Point3d operator / (const double &val){if (val != 0.0) return Point3d(x / val, y / val, z / val);}
		bool operator ==(const Point3d &pt){return ((fabs(pt.x - x) < 1e-8)&&(fabs(pt.y - y) < 1e-8)&&(fabs(pt.z - z) < 1e-8));}
		double GetSquaredLength(){return x * x + y * y + z * z;}
	};
	typedef Point3d Vector3d;
	typedef shared_ptr<Point3d> ptr_Point;
	typedef vector<Point3d> Pointlist;

	struct Triangle3
	{
		int vert[3];
		Triangle3(){;}
		Triangle3(int a, int b, int c){vert[0] = a; vert[1] = b; vert[2] = c;}
	};
	typedef shared_ptr<Triangle3> ptr_Triangle;
	typedef vector<Triangle3> Trianglelist;

	struct Polygon3
	{
		vector<int> ExteriorRing;
		vector<vector<int>> InteriorRings;
	};
	typedef shared_ptr<Polygon3> ptr_Polygon;
	typedef vector<Polygon3> Polygonlist;

	struct Surface3
	{
		Trianglelist facets;
	};

	struct Polyhedron3
	{
		Trianglelist facets;
	};

	struct BoundingBox
	{
		Point3d Max;
		Point3d Min;

		BoundingBox(){};
		BoundingBox(const Point3d &ptMax, const Point3d &ptMin):Max(ptMax), Min(ptMin){}
		BoundingBox(const Pointlist&);
		BoundingBox& operator =(const BoundingBox &box){Max = box.Max; Min = box.Min; return (*this);}
		Vector3d GetSize();
		double GetMaxSize();
	};

	struct Indice3i
	{
		int x, y, z;

		Indice3i(){};
		Indice3i(int in_x, int in_y, int in_z):x(in_x),y(in_y),z(in_z){}
		Indice3i operator +(const Indice3i &pt){return Indice3i(pt.x + x, pt.y + y, pt.z + z);}
		Indice3i operator -(const Indice3i &pt){return Indice3i(x - pt.x, y - pt.y, z - pt.z);}
		Indice3i operator *(const int &val){return Indice3i(x * val, y * val, z * val);}
		Indice3i& operator =(const Indice3i &pt){x = pt.x; y = pt.y; z = pt.z; return (*this);}
		bool operator ==(const Indice3i &pt){return (pt.x == x)&&(pt.y == y)&&(pt.z == z);}
		bool operator !=(const Indice3i &pt){return (pt.x != x)||(pt.y != y)||(pt.z != z);}
	};
	typedef vector<Indice3i> IndicesList;

}